<template>
  <div class="component-container">
    <!-- 搜索表单 -->
    <el-form ref="queryFormRef" :model="queryParams" :inline="true">
      <el-form-item>
        <el-button type="success" :icon="Plus" @click="handleAdd">新增</el-button>
      </el-form-item>

      <!-- 数据表格 -->
      <el-form-item prop="name">
        <el-input
          v-model="queryParams.name"
          placeholder="菜单名称"
          clearable
          @keyup.enter="handleQuery"
        />
      </el-form-item>

      <el-form-item>
        <el-button type="primary" :icon="Search" @click="handleQuery">搜索</el-button>
        <el-button :icon="Refresh" @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form>

    <!-- 数据表格 -->
    <el-table
      v-loading="loading"
      :data="menuButtonList"
      highlight-current-row
      :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
      @row-click="handleRowClick"
      row-key="id"
      border
      style="width: 100%"
    >
      <el-table-column label="菜单名称" align="center" min-width="45%">
        <template #default="scope">
          <svg-icon
            color="#333"
            :icon-class="scope.row.icon ? scope.row.icon : 'build'"
          />
          {{ scope.row.name }}
        </template>
      </el-table-column>

      <el-table-column label="状态" align="center" min-width="15%">
        <template #default="scope">
          <el-tag v-if="scope.row.hidden" type="info">隐藏</el-tag>
          <el-tag v-else type="success">显示</el-tag>
        </template>
      </el-table-column>

      <el-table-column label="排序" prop="sort" align="center" min-width="15%"/>

      <el-table-column label="操作" align="center" min-width="30%">
        <template #default="scope">
          <el-button
            type="success"
            :icon="Plus"
            circle
            plain
            @click.stop="handleAdd(scope.row)"
          />
          <el-button
            type="primary"
            :icon="Edit"
            circle
            plain
            @click.stop="handleUpdate(scope.row)"
          />
          <el-button
            type="danger"
            :icon="Delete"
            circle
            plain
            @click.stop="handleDelete(scope.row)"
          />
        </template>
      </el-table-column>
    </el-table>

    <!-- 弹窗表单 -->
    <el-dialog
      :title="dialog.title"
      v-model="dialog.visible"
      @close="cancel"
      width="750px"
    >
      <el-form
        ref="dataFormRef"
        :model="formData"
        :rules="rules"
        label-width="100px"
      >
        <el-form-item label="父级" prop="pid">
          <el-tree-select
            v-model="formData.pid"
            placeholder="选择上级菜单"
            :data="menuOptions"
            filterable
            check-strictly
          />
        </el-form-item>

        <el-form-item label="名称" prop="name">
          <el-input v-model="formData.name" placeholder="请输入菜单名称"/>
        </el-form-item>

        <el-form-item label="类型">
          <el-radio-group v-model="formData.type" @change="handleMenuTypeChange">
            <el-radio label="menu">目录</el-radio>
            <el-radio label="carte">菜单</el-radio>
            <el-radio label="link">外链</el-radio>
          </el-radio-group>
        </el-form-item>

        <!-- 路由路径(浏览器地址栏显示) -->
        <el-form-item v-if="formData.type == 'link'" label="外链地址" prop="path">
          <el-input v-model="formData.path" placeholder="请输入外链完整路径"/>
        </el-form-item>

        <el-form-item v-else label="路径" prop="path">
          <el-input v-if="formData.type == 'menu'" v-model="formData.path" placeholder="/system  (注意:目录以/开头)"/>
          <el-input v-else v-model="formData.path" placeholder="user"/>
        </el-form-item>

        <!-- 组件页面完整路径 -->
        <el-form-item v-if="formData.type == 'carte'" label="组件" prop="component">
          <el-input v-model="formData.component" placeholder="system/user/index">
            <template v-if="formData.pid != -999 && !formData.pid" #prepend>src/views/</template>
            <template v-if="formData.pid != -999 && !formData.pid" #append>.vue</template>
          </el-input>
        </el-form-item>

        <el-form-item label="图标" prop="icon">
          <el-popover ref="popoverRef" placement="bottom-start" :width="570" trigger="click">
            <template #reference>
              <el-input v-model="formData.icon" placeholder="点击选择图标" readonly @click="iconSelectVisible = true">
                <template #prefix>
                  <svg-icon :icon-class="formData.icon"/>
                </template>
              </el-input>
            </template>
            <icon-select @selected="selected"/>
          </el-popover>
        </el-form-item>

        <el-form-item label="跳转">
          <el-input v-model="formData.redirect" placeholder="重定向" maxlength="50"/>
        </el-form-item>

        <el-form-item label="状态">
          <el-radio-group v-model="formData.hidden">
            <el-radio :label="false">显示</el-radio>
            <el-radio :label="true">隐藏</el-radio>
          </el-radio-group>
        </el-form-item>

        <el-form-item label="排序" prop="sort">
          <el-input-number v-model="formData.sort" style="width: 100px" controls-position="right" :min="0"/>
        </el-form-item>

      </el-form>

      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm">确 定</el-button>
          <el-button @click="cancel">取 消</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
  import {reactive, ref, onMounted, toRefs} from 'vue';

  import {Search, Plus, Edit, Refresh, Delete} from '@element-plus/icons-vue';
  import {ElForm, ElMessage, ElMessageBox, ElPopover} from 'element-plus';

  import {Dialog, Option} from '@/types/common';

  import {
    MenuFormData,
    MenuItem,
    MenuQueryParam,
  } from '@/types/api/system/menu';
  // API 依赖
  import {
    listMenus,
    getMenuDetail,
    listSelectMenus,
    addMenu,
    deleteMenus,
    updateMenu,
  } from '@/api/system/menu';

  import SvgIcon from '@/components/SvgIcon/index.vue';
  import IconSelect from '@/components/IconSelect/index.vue';

  const emit = defineEmits(['menuClick']);
  const queryFormRef = ref(ElForm);
  const dataFormRef = ref(ElForm);
  const popoverRef = ref(ElPopover);

  const state = reactive({
    loading: true,
    // 选中ID数组
    ids: [],
    // 非单个禁用
    single: true,
    // 非多个禁用
    multiple: true,
    queryParams: {} as MenuQueryParam,
    menuButtonList: [] as MenuItem[],
    dialog: {visible: false} as Dialog,
    formData: {
      id: '',
      pid: '',
      name: '',
      type: 'carte',
      sort: 0,
      hidden: false,
      component: 'Layout',
    } as MenuFormData,
    rules: {
      pid: [{required: true, message: '请选择顶级菜单', trigger: 'blur'}],
      name: [{required: true, message: '请输入菜单名称', trigger: 'blur'}],
      type: [{required: true, message: '请选择菜单类型', trigger: 'blur'}],
      path: [{required: true, message: '请输入路由路径', trigger: 'blur'}],
      component: [
        {required: true, message: '请输入组件完整路径', trigger: 'blur'},
      ],
    },
    menuOptions: [] as Option[],
    currentRow: undefined,
    // Icon选择器显示状态
    iconSelectVisible: false,
    cacheData: {
      menuType: '',
      menuPath: '',
    },
  });

  const {
    loading,
    queryParams,
    menuButtonList,
    dialog,
    formData,
    rules,
    menuOptions,
    iconSelectVisible,
    cacheData,
  } = toRefs(state);

  /**
   * 查询
   */
  function handleQuery() {
    // 重置父组件
    emit('menuClick', null);
    state.loading = true;
    listMenus(state.queryParams).then(({data}) => {
      state.menuButtonList = data;
      state.loading = false;
    });
  }

  /**
   * 加载菜单下拉树
   */
  async function loadMenuData() {
    const menuOptions: any[] = [];
    await listSelectMenus().then(({data}) => {
      const menuOption = {value: -999, label: '顶级菜单', children: data};
      menuOptions.push(menuOption);
      state.menuOptions = menuOptions;
    });
  }

  /**
   * 重置查询
   */
  function resetQuery() {
    queryFormRef.value.resetFields();
    handleQuery();
  }

  function handleRowClick(row: any) {
    state.currentRow = JSON.parse(JSON.stringify(row));
    emit('menuClick', row);
  }

  async function handleAdd(row: any) {
    state.formData.id = undefined;
    await loadMenuData();
    state.dialog = {
      title: '添加菜单',
      visible: true,
    };
    if (row.id) {
      // 行点击新增

      state.formData.pid = row.id;
      if (row.id == '-999' || row.id == '') {
        state.formData.type = 'carte';
      } else {
        state.formData.type = 'menu';
      }
    } else {
      // 工具栏新增
      if (state.currentRow) {
        state.formData.pid = (state.currentRow as any).id;
        state.formData.type = 'menu';
      } else {
        state.formData.pid = '';
        state.formData.type = 'carte';
      }
    }
  }

  /**
   * 修改弹窗
   */
  async function handleUpdate(row: any) {
    await loadMenuData();
    state.dialog = {
      title: '修改菜单',
      visible: true,
    };
    const id = row.id || state.ids;
    getMenuDetail(id).then(({data}) => {
      state.formData = data;
      cacheData.value.menuType = data.type;
      cacheData.value.menuPath = data.path;
    });
  }

  /**
   * 菜单类型change事件
   */
  function handleMenuTypeChange(val: any) {
    if (val !== cacheData.value.menuType) {
      formData.value.path = '';
    } else {
      formData.value.path = cacheData.value.menuPath;
    }
  }

  /**
   * 菜单提交
   */
  function submitForm() {
    dataFormRef.value.validate((isValid: boolean) => {
      if (isValid) {
      if (state.formData.id) {
        updateMenu(state.formData.id, state.formData).then(() => {
            ElMessage.success('修改成功');
            cancel();
            handleQuery();
          });
        } else {
          addMenu(state.formData).then(() => {
            ElMessage.success('新增成功');
            cancel();
            handleQuery();
          });
        }
      }
    });
  }

  function handleDelete(row: any) {
    const ids = [row.id || state.ids].join(',');
    ElMessageBox.confirm('确认删除已选中的数据项?', '警告', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning',
    })
      .then(() => {
        deleteMenus(ids).then(() => {
          ElMessage.success('删除成功');
          handleQuery();
        });
      })
      .catch(() => ElMessage.info('已取消删除'));
  }

  /**
   * 取消关闭弹窗
   */
  function cancel() {
    dataFormRef.value.resetFields();
    state.dialog.visible = false;
  }

  /**
   * 选择图标后事件
   */
  function selected(name: string) {
    state.formData.icon = name;
    state.iconSelectVisible = false;
  }

  onMounted(() => {
    handleQuery();
  });
</script>
